﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="RoleClassLibViewModel.cs" >
//   J. Prinz
// </copyright>
// <summary>
//   ViewModel representing a RoleClassLibrary <see cref="RoleClassLibType" />
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace AutomationMLMapper.ViewModels.CAEXObjectViewModels
{
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using AMLEngineExtensions;
    using CAEX_ClassModel;
    using AutomationMLMapper.AutomationML.Extensions;
    using AutomationMLMapper.Properties;
    using AutomationMLMapper.ViewModels.CAEXObjectCollectionViewModels;
    using AutomationMLMapper.ViewModels.SystemViewModels;
    using AutomationMLMapper.ViewModels.PaneViewModels;
    using AutomationMLMapper.MVVM_Framework;

    /// <summary>
    ///   ViewModel representing a RoleClassLibrary <see cref="RoleClassLibType" />
    /// </summary>
    public class RoleClassLibViewModel : CAEXObjectViewModel<RoleClassLibType>
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="RoleClassLibViewModel"/> class. 
        /// </summary>
        /// <param name="element">
        /// a CAEX - RoleClassLib-Element 
        /// </param>
        public RoleClassLibViewModel(RoleClassLibType element)
            : base(element)
        {
            Name = element.Name.Value;
        }

        #endregion

        #region Public Properties

        /// <summary>
        ///   DisplayName of the CAEX-Element in the UI used in Headers and Labels
        /// </summary>
        public static new string DisplayName
        {
            get
            {
                return "RoleClass Library";
            }
        }

               
        /// <summary>
        ///  Gets and sets the HasPartner
        /// </summary>
        public bool HasPartner
        {
            get { return PartnerLibrary!=null; }
        }

        /// <summary>
        ///  <see cref="PartnerLibrary"/>
        /// </summary>    
        private RoleClassLibViewModel partnerLibrary;

        /// <summary>
        /// The RoleClass - Library of the Partner which should match this Library
        /// </summary>
        public RoleClassLibViewModel PartnerLibrary {
            get { return partnerLibrary; }
            set { partnerLibrary = value;
                OnNotifyPropertyChanged("HasPartner");
                OnNotifyPropertyChanged("PartnerLibrary");
                OnNotifyPropertyChanged("HasExportPartner");
                OnNotifyPropertyChanged("HasImportPartner");
            }
        }

        public bool IsDifferent
        {
            get 
            {
                return
                    (MissingInPartner != null && MissingInPartner.Elements.Count > 0) ||
                    (AddedInPartner != null && AddedInPartner.Elements.Count > 0) ||
                    (ChangedInPartner != null && ChangedInPartner.Elements.Count > 0);
            
            }
        }

        /// <summary>
        /// The Missing RoleClasses in the Partner Library
        /// </summary>
        public RoleClassCollectionViewModel MissingInPartner { get; set; }

        /// <summary>
        /// The Added RoleClasses in the Partner Library
        /// </summary>
        public RoleClassCollectionViewModel AddedInPartner { get; set; }

        /// <summary>
        /// The Changed RoleClasses in the Partner Library
        /// </summary>
        public RoleClassCollectionViewModel ChangedInPartner { get; set; }

        /// <summary>
        ///  <see cref="VersionsAreEqual"/>
        /// </summary>    
        private bool versionsAreEqual;

        /// <summary>
        ///  Gets and sets the VersionsAreEqual
        /// </summary>
        public bool VersionsAreEqual
        {
            get { return versionsAreEqual; }
            set { versionsAreEqual = value;  OnNotifyPropertyChanged  ("VersionsAreEqual"); }
        }
        

        /// <summary>
        ///  <see cref="Owner"/>
        /// </summary>    
        private SystemViewModel owner;

        /// <summary>
        ///  Gets and sets the Owner of the RoleClass - Library
        /// </summary>
        public SystemViewModel Owner
        {
            get { return owner; }
            set { owner = value; 
                OnNotifyPropertyChanged ("Owner");
                OnNotifyPropertyChanged ("HasExportPartner");
                OnNotifyPropertyChanged ("HasImportPartner");
            }
        }

        public bool HasExportPartner
        {
            get
            {
                return ((Owner != null && Owner.SystemType == Resources.ExportSystem) ||
                    (PartnerLibrary != null) && (PartnerLibrary.Owner.SystemType == Resources.ExportSystem)) && !IsDifferent;
            }
        }

        public bool HasImportPartner
        {
            get
            {
                return ((Owner != null && Owner.SystemType == Resources.ImportSystem) ||
                    (PartnerLibrary != null) && (PartnerLibrary.Owner.SystemType == Resources.ImportSystem)) && !IsDifferent;
            }
        }

        /// <summary>
        /// Get All RoleClasses from this RoleClass - Library
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public IEnumerable<RoleFamilyType> AllRoleClasses
        {
            get 
            {
                foreach (RoleFamilyType RoleClass in GetAllRoleClasses ( CaexObject.RoleClass ))
                {
                    yield return RoleClass;
                }
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Compare this RoleClass Library with the Partner Library
        /// </summary>
        public void CompareWithPartner ()
        {
            AddedInPartner   = new RoleClassCollectionViewModel(this);
            MissingInPartner = new RoleClassCollectionViewModel(this);
            ChangedInPartner = new RoleClassCollectionViewModel(this);

            List<RoleFamilyType> CheckedRoleClasses = new List<RoleFamilyType>();
            
            if (PartnerLibrary != null)
            {
                if (this.CaexObject.Version == null && PartnerLibrary.CaexObject.Version == null)
                {
                    VersionsAreEqual = true;
                }
                else
                {
                    VersionsAreEqual = (this.CaexObject.Version != null && PartnerLibrary.CaexObject.Version != null)
                             && this.CaexObject.Version.Value.Equals(PartnerLibrary.CaexObject.Version.Value);
                }

                foreach (RoleFamilyType RoleClass in PartnerLibrary.AllRoleClasses)
                {
                    var myRoleClass = Owner.AmlDocumentRepresentation.CaexObject.FindFastByPath(RoleClass.CAEXPath()) as RoleFamilyType;
                    if (myRoleClass == null)
                        AddedInPartner.Elements.Add(new RoleClassViewModel (RoleClass));
                    else
                    {
                        CheckedRoleClasses.Add(myRoleClass);

                        if (myRoleClass.RoleClassEquals (RoleClass, true).HasFlag (CaexObjectComparerResult.RoleClassDiff))
                            ChangedInPartner.Elements.Add(new RoleClassViewModel(RoleClass));
                    }
                }

                foreach (RoleFamilyType RoleClass in AllRoleClasses)
                {
                    if (!CheckedRoleClasses.Any ( rc=> rc.CAEXPath() == RoleClass.CAEXPath() ))
                        MissingInPartner.Elements.Add(new RoleClassViewModel (RoleClass));
                }
            }

            OnNotifyPropertyChanged ("IsDifferent");
            OnNotifyPropertyChanged ("HasExportPartner");
            OnNotifyPropertyChanged ("HasImportPartner");
        }
        #endregion

        /// <summary>
        ///  <see cref="ShowRoleLibDifference"/>
        /// </summary>    
        private RelayCommand<object> showRoleLibDifference;

        /// <summary>
        ///  The ShowRoleLibDifference - Command
        /// </summary>
        public System.Windows.Input.ICommand ShowRoleLibDifference
        {
            get
            {
                return this.showRoleLibDifference
                ??
                (this.showRoleLibDifference = new RelayCommand<object>(this.ShowRoleLibDifferenceExecute, this.ShowRoleLibDifferenceCanExecute));
            }
        }

        /// <summary>
        ///  The <see cref="ShowRoleLibDifference"/> Execution Action.
        /// </summary>
        /// <param name="parameter">
        ///  TODO The parameter. 
        /// </param>        
        private void ShowRoleLibDifferenceExecute(object parameter)
        {
            DifferentRolesViewModel diffViewModel = AutomationMLMapperViewModel.MainViewModel.AutomationMLTools.OfType<DifferentRolesViewModel>().
                SingleOrDefault() as DifferentRolesViewModel;

            if (diffViewModel == null)
            {
                diffViewModel = new DifferentRolesViewModel()
                {
                    CollectionOwner = this,
                    AddedRolesCollection = this.AddedInPartner,
                    ChangedRolesCollection = this.ChangedInPartner,
                    MissingRolesCollection = this.MissingInPartner
                };

                diffViewModel.AddedRolesCollection.IsExpanded = true;
                diffViewModel.ChangedRolesCollection.IsExpanded = true;
                diffViewModel.MissingRolesCollection.IsExpanded = true;

                AutomationMLMapperViewModel.MainViewModel.AddAutomationMLTool(diffViewModel);
            }
            else
            {
                diffViewModel.CollectionOwner = this;
                diffViewModel.AddedRolesCollection = this.AddedInPartner;
                diffViewModel.ChangedRolesCollection = this.ChangedInPartner;
                diffViewModel.MissingRolesCollection = this.MissingInPartner;
            }
        }

        /// <summary>
        ///  Test, if the <see cref="ShowRoleLibDifference"/> can execute.
        /// </summary>
        /// <param name="parameter">
        ///  TODO The parameter. 
        /// </param>  
        /// <returns>
        ///  true, if command can execute
        /// </returns> 
        private bool ShowRoleLibDifferenceCanExecute(object parameter)
        {
            return IsDifferent;
        }
        #region private Methods
        /// <summary>
        /// Get All RoleClasses from the collection and sub-collections
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        private IEnumerable <RoleFamilyType> GetAllRoleClasses ( IEnumerable collection)
        {
            foreach (RoleFamilyType RoleClass in collection)
            {
                yield return RoleClass;
                foreach (RoleFamilyType ChildRoleClass in GetAllRoleClasses(RoleClass.RoleClass))
                    yield return ChildRoleClass;
            }
        }

        
        #endregion
    }
}